/*
 * SocketFrame.java
 *
 * Created on Jul 15, 2011, 10:33:44 AM
 */
package com.hc.util.net.ui;

import com.hc.util.net.SocketListener;
import com.hc.util.net.SocketUtil;
import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.UIManager;

/**
 *
 * @author fenfei
 */
public class SocketFrame extends javax.swing.JFrame implements SocketListener {

    SocketUtil net = new SocketUtil();

    /** Creates new form SocketFrame */
    public SocketFrame() {
        net.setListener(this);
        initComponents();
        uiSetting();
    }
    
    void uiSetting(){
        
        langBtnGrp.add(enMenu);
        langBtnGrp.add(zhMenu);
        
        localeMIs.clear();
        localeMIs.put(Locale.ENGLISH, enMenu);
        localeMIs.put(Locale.PRC, zhMenu);
        
        enMenu.setLocale(Locale.ENGLISH);
        zhMenu.setLocale(Locale.PRC);
        JRadioButtonMenuItem dftLanMI=localeMIs.get(Locale.getDefault());
        if(dftLanMI==null)
            dftLanMI=enMenu;
        dftLanMI.setSelected(true);
    }
    
    Map<Locale,JRadioButtonMenuItem> localeMIs=new HashMap();

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        msgPaneMenu = new javax.swing.JPopupMenu();
        closeConnMI = new javax.swing.JMenuItem();
        rmTabMI = new javax.swing.JMenuItem();
        langBtnGrp = new javax.swing.ButtonGroup();
        jLabel1 = new javax.swing.JLabel();
        servPortFld = new javax.swing.JTextField();
        servBtn = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        ipFld = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        portFld = new javax.swing.JTextField();
        connBtn = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        inArea = new javax.swing.JTextArea();
        sendBtn = new javax.swing.JButton();
        tabPane = new javax.swing.JTabbedPane();
        sendHttpBtn = new javax.swing.JButton();
        mbar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        exitMenu = new javax.swing.JMenuItem();
        optnMenu = new javax.swing.JMenu();
        newWinMenu = new javax.swing.JMenuItem();
        langMenu = new javax.swing.JMenu();
        enMenu = new javax.swing.JRadioButtonMenuItem();
        zhMenu = new javax.swing.JRadioButtonMenuItem();
        helpMenu = new javax.swing.JMenu();
        aboutMenu = new javax.swing.JMenuItem();

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/hc/util/net/ui/lang"); // NOI18N
        closeConnMI.setText(bundle.getString("closeConn")); // NOI18N
        closeConnMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeConnMIActionPerformed(evt);
            }
        });
        msgPaneMenu.add(closeConnMI);

        rmTabMI.setText(bundle.getString("rmTab")); // NOI18N
        rmTabMI.setToolTipText(bundle.getString("rmTabTip")); // NOI18N
        rmTabMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rmTabMIActionPerformed(evt);
            }
        });
        msgPaneMenu.add(rmTabMI);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle(bundle.getString("socketUtil")); // NOI18N

        jLabel1.setText(bundle.getString("port")); // NOI18N

        servPortFld.setText("7832");

        servBtn.setText(bundle.getString("serve")); // NOI18N
        servBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                servBtnActionPerformed(evt);
            }
        });

        jLabel2.setText("IP：");

        ipFld.setText(bundle.getString("SocketFrame.ipFld.text")); // NOI18N

        jLabel3.setText(bundle.getString("port")); // NOI18N

        portFld.setText("80");

        connBtn.setText(bundle.getString("connect")); // NOI18N
        connBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connBtnActionPerformed(evt);
            }
        });

        inArea.setColumns(20);
        inArea.setRows(5);
        jScrollPane2.setViewportView(inArea);

        sendBtn.setText(bundle.getString("send")); // NOI18N
        sendBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendBtnActionPerformed(evt);
            }
        });

        tabPane.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                tabPaneMousePressed(evt);
            }
        });

        sendHttpBtn.setText(bundle.getString("SocketFrame.sendHttpBtn.text")); // NOI18N
        sendHttpBtn.setToolTipText(bundle.getString("SocketFrame.sendHttpBtn.toolTipText")); // NOI18N
        sendHttpBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendHttpBtnActionPerformed(evt);
            }
        });

        fileMenu.setText(bundle.getString("file")); // NOI18N

        exitMenu.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, java.awt.event.InputEvent.CTRL_MASK));
        exitMenu.setText(bundle.getString("exit")); // NOI18N
        exitMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenu);

        mbar.add(fileMenu);

        optnMenu.setText(bundle.getString("option")); // NOI18N

        newWinMenu.setText(bundle.getString("newWin")); // NOI18N
        newWinMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newWinMenuActionPerformed(evt);
            }
        });
        optnMenu.add(newWinMenu);

        langMenu.setText(bundle.getString("lang")); // NOI18N

        enMenu.setSelected(true);
        enMenu.setText("English");
        enMenu.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                langMenuChanged(evt);
            }
        });
        langMenu.add(enMenu);

        zhMenu.setSelected(true);
        zhMenu.setText("简体中文");
        zhMenu.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                langMenuChanged(evt);
            }
        });
        langMenu.add(zhMenu);

        optnMenu.add(langMenu);

        mbar.add(optnMenu);

        helpMenu.setText(bundle.getString("help")); // NOI18N

        aboutMenu.setText(bundle.getString("about")); // NOI18N
        aboutMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuActionPerformed(evt);
            }
        });
        helpMenu.add(aboutMenu);

        mbar.add(helpMenu);

        setJMenuBar(mbar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 575, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 522, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(sendHttpBtn, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE)
                            .addComponent(sendBtn)))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addComponent(jLabel1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(servPortFld)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(servBtn))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addComponent(jLabel2)
                                .addGap(18, 18, 18)
                                .addComponent(ipFld, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(portFld, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(connBtn)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(servPortFld, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(servBtn))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(ipFld, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(portFld, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(connBtn))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tabPane, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(sendBtn)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(sendHttpBtn))
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
    ResourceBundle lang = ResourceBundle.getBundle("com/hc/util/net/ui/lang");
    List<Socket> sockets;
    private void servBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_servBtnActionPerformed
        try {
            if (net.isServerRunning()) {
                net.stopServer();
            } else {

                net.serve(servPortFld.getText());
            }
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(this, ex);
            // Logger.getLogger(SocketFrame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this, ex);
            // Logger.getLogger(SocketFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_servBtnActionPerformed

    private void connBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connBtnActionPerformed
        try {
            net.connect(ipFld.getText(), portFld.getText());
        } catch (Exception ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, "连接失败！");
            if(evt.getSource()==this.sendHttpBtn){
                portFld.setText("80");
                try {
                    net.connect(ipFld.getText(), portFld.getText());
                } catch (Exception ex1) {
                    Logger.getLogger(SocketFrame.class.getName()).log(Level.SEVERE, null, ex1);
                }
            }
        }
    }//GEN-LAST:event_connBtnActionPerformed

    private void sendBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendBtnActionPerformed
      if(send(inArea.getText()))
          inArea.setText("");
    }//GEN-LAST:event_sendBtnActionPerformed

    private boolean send(String msg){
        MessagePane mp = null;
        try {
            JScrollPane sp = (JScrollPane) tabPane.getSelectedComponent();
            for(Socket s: msgPanes.keySet()){
                mp=(MessagePane) sp.getViewport().getView();
                if(mp == msgPanes.get(s)){
                    net.send(msg, s);
                    mp.appendOutMsg(msg);
                    return true;
                }
            }
        } catch (Exception ex) {
            mp.appendError(lang.getString("sendMsgFail")+ex);
        }
        return false;
    }
    
    private void tabPaneMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tabPaneMousePressed
       if(tabPane.getTabCount()==0 || evt.getButton()!=MouseEvent.BUTTON3)
           return;
        msgPaneMenu.show(evt.getComponent(), evt.getX(), evt.getY());
    }//GEN-LAST:event_tabPaneMousePressed

    private void rmTabMIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rmTabMIActionPerformed
        closeConnMIActionPerformed(evt);
        tabPane.removeTabAt(tabPane.getSelectedIndex());
    }//GEN-LAST:event_rmTabMIActionPerformed

    private void closeConnMIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeConnMIActionPerformed
       JScrollPane sp = (JScrollPane) tabPane.getSelectedComponent();
            for(Socket s: msgPanes.keySet()){
                if(sp.getViewport().getView() == msgPanes.get(s)){
                try {
                    if(s.isClosed()){
                         ((MessagePane)sp.getViewport().getView()).appendError(lang.getString("multiConnCloseTip"));
                    }else{
                       s.close(); 
                    }
                    if(evt.getSource()==this.rmTabMI){
                        msgPanes.remove(s);
                    }
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, ex);
                }
                    break;
                }
            }
    }//GEN-LAST:event_closeConnMIActionPerformed

    private void exitMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuActionPerformed
       System.exit(0);
    }//GEN-LAST:event_exitMenuActionPerformed

    private void langMenuChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_langMenuChanged
       if(evt.getStateChange()==ItemEvent.SELECTED){
           JRadioButtonMenuItem mi=(JRadioButtonMenuItem) evt.getItem();
           if(mi.getLocale()==Locale.getDefault())
               return;
            Locale.setDefault(mi.getLocale());
            System.out.println("set lang:"+Locale.getDefault());
            new SocketFrame().setVisible(true);
       }
       
    }//GEN-LAST:event_langMenuChanged

    private void newWinMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newWinMenuActionPerformed
        new SocketFrame().setVisible(true);
    }//GEN-LAST:event_newWinMenuActionPerformed

    private void aboutMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuActionPerformed
        
        JEditorPane page=new JEditorPane("text/html","<html>Update: http://code.google.com/p/network-utility <br>Blog: <a href='http://blog.sina.com.cn/u/1881965495'>http://blog.sina.com.cn/u/1881965495</a><br>Mail: zengfenfei@gmail.com<br><br>Socket Utility 1.0<br>License: Apache License, 2.0 (Apache-2.0)</html>");
        page.setEditable(false);
        
        JOptionPane.showMessageDialog(this, page);
    }//GEN-LAST:event_aboutMenuActionPerformed

    private void sendHttpBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendHttpBtnActionPerformed
       connBtnActionPerformed(evt);
       String host=ipFld.getText()+":"+portFld.getText();
       String req="GET / HTTP/1.1\nUser-Agent: Opera/9.80 (X11; Linux i686; U; en) Presto/2.9.168 Version/11.50\nHost: "+host+"\nAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1\nAccept-Language: en-US,en;q=0.9\nAccept-Encoding: gzip, deflate\nConnection: Keep-Alive\n";
       this.send(req);
    }//GEN-LAST:event_sendHttpBtnActionPerformed
   
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (ClassNotFoundException ex) {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception ex1) {
                Logger.getLogger(SocketFrame.class.getName()).log(Level.SEVERE, null, ex1);
            }
        } catch (Exception ex) {
            Logger.getLogger(SocketFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new SocketFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenu;
    private javax.swing.JMenuItem closeConnMI;
    private javax.swing.JButton connBtn;
    private javax.swing.JRadioButtonMenuItem enMenu;
    private javax.swing.JMenuItem exitMenu;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JTextArea inArea;
    private javax.swing.JTextField ipFld;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.ButtonGroup langBtnGrp;
    private javax.swing.JMenu langMenu;
    private javax.swing.JMenuBar mbar;
    private javax.swing.JPopupMenu msgPaneMenu;
    private javax.swing.JMenuItem newWinMenu;
    private javax.swing.JMenu optnMenu;
    private javax.swing.JTextField portFld;
    private javax.swing.JMenuItem rmTabMI;
    private javax.swing.JButton sendBtn;
    private javax.swing.JButton sendHttpBtn;
    private javax.swing.JButton servBtn;
    private javax.swing.JTextField servPortFld;
    private javax.swing.JTabbedPane tabPane;
    private javax.swing.JRadioButtonMenuItem zhMenu;
    // End of variables declaration//GEN-END:variables

    @Override
    public void serverStarted(ServerSocket serverS) {
        servBtn.setText(lang.getString("stopServ"));
        servPortFld.setEditable(false);
        servPortFld.setToolTipText(SocketUtil.getIPv4s().toString());
      
    }

    @Override
    public void serverStopped() {
        servBtn.setText(lang.getString("serve"));
        servPortFld.setEditable(true);
        servPortFld.setToolTipText("");
    }

    @Override
    public void connectionEstablished(Socket socket) {
        String dst = socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
        MessagePane pane = new MessagePane();
        pane.appendInfo("A connection is created:<br>"+"Local: "+socket.getLocalSocketAddress()+"<br>Remote: "+socket.getRemoteSocketAddress());
        tabPane.addTab(dst, null, new JScrollPane(pane), lang.getString("local")+socket.getLocalAddress()+":"+socket.getLocalPort());
        tabPane.setSelectedComponent(pane.getParent().getParent());
        msgPanes.put(socket, pane);
    }
    
    @Override
    public void connectionClosed(Socket socket) {
        MessagePane mp=msgPanes.get(socket);
        mp.appendInfo(lang.getString("msgReceiveThrdStopTip"));
      //  tabPane.remove(.getParent().getParent());
   }
    Map<Socket, MessagePane> msgPanes = new HashMap<Socket, MessagePane>();

    @Override
    public void onMessage(String msg, Socket sender) {
        msgPanes.get(sender).appendInMsg(msg);
    }
}
